home *** CD-ROM | disk | FTP | other *** search
/ CD ROM Paradise Collection 4 / CD ROM Paradise Collection 4 1995 Nov.iso / program / swagg_m.zip / MEMORY.SWG / 0019_Calls to EMS Manager.pas < prev    next >
Pascal/Delphi Source File  |  1993-06-22  |  10KB  |  305 lines

  1. {*************************** EMS.PAS ************************
  2. *** Demonstrate calls to Extended memory manager          ***
  3. ************************************************************}
  4.  
  5. USES
  6.  
  7.   Crt,Dos;
  8.  
  9. {***************************************************************}
  10.  
  11. TYPE
  12.   PtrType = RECORD                  {Define a pointer record    }
  13.     Offset  : Word;                 {  type so we can access the}
  14.     Segment : Word                  {  individual pointer fields}
  15.     END;
  16.   DeviceName = ARRAY[1..8] OF Char; {Defined to test device Name}
  17.  
  18. CONST
  19.  
  20.   EmsInt      = $67;                {EMS Interrupt number       }
  21.   IOCtlFunc   = $44;                {IOCtl DOS Function number  }
  22.   PageLen     = 16384;              {Length of memory page      }
  23.   MsgLen      = 16;                 {Message len plus len byte  }
  24.   MsgsPerPage = PageLen DIV MsgLen; {Number of messages in page }
  25.   NumMsgs     = 5000;               {Number EMS messages        }
  26.  
  27.   {*** Emm functions ***}
  28.  
  29.   GetStatus        = $40;
  30.   GetPageFrameAddr = $41;
  31.   GetUnallocPages  = $42;
  32.   GetEmmVersion    = $46;
  33.   AllocatePages    = $43;
  34.   MapHandlePage    = $44;
  35.   DeallocatePages  = $45;
  36.  
  37. VAR
  38.   P0, P1, P2, P3 : Pointer;     {Pointers to physical pages     }
  39.   EmmHandle      : Integer;     {Handle for EMM allocated pages }
  40.   Tmp            : FILE;        {Temp file to test if EMM exists}
  41.   MsgBuf         : Pointer;     {Pointer into mapped memory     }
  42.   Buff           : String[15];  {Buffer for msg stored in EM    }
  43.   I              : Integer;     {Dummy variable                 }
  44.   EmmRegs        : Registers;   {Registers for interrupt calls  }
  45.   Page,Index     : Integer;     {Used to address page frame     }
  46.   EmsVector      : Pointer;     {EMM address from Int $67       }
  47.   StrNum         : String[4];   {Holds record # for EMM msg     }
  48.  
  49. {******** Function to convert word value to Hex string *********}
  50.  
  51. FUNCTION Hex(IntNbr : Word): String;
  52. CONST
  53.   HexDigit :ARRAY[0..15] OF Char = '0123456789ABCDEF';
  54. VAR
  55.   S        : String[2];         {Temporary String}
  56.   TempByte : Byte;
  57. BEGIN
  58.   TempByte := Hi(IntNbr);                  {Convert upper nibble}
  59.   S := HexDigit[TempByte DIV 16] +
  60.        HexDigit[TempByte MOD 16];
  61.   TempByte := Lo(IntNbr);                  {Convert lower nibble}
  62.   Hex := S + HexDigit[TempByte DIV 16] +
  63.              HexDigit[TempByte MOD 16];
  64. END;
  65.  
  66. {******** Create a string that contains a pointer value ********}
  67.  
  68. FUNCTION PrintPointer(P : Pointer): String;
  69.  
  70. BEGIN
  71.   PrintPointer := Hex(PtrType(P).Segment) + ':' +
  72.                   Hex(PtrType(P).Offset);
  73.   END;
  74.  
  75. {*********** Print the EMM Status to the screen ****************}
  76.  
  77. PROCEDURE EmmPrintStatus(Status: Byte);
  78.  
  79. CONST
  80.   EmmStatus : ARRAY [$80..$8F] OF String =
  81.     ('Driver malfunction',
  82.      'Hardware malfunction',
  83.      '',
  84.      'Bad Handle',
  85.      'Undefined FUNCTION',
  86.      'No free handles',
  87.      'Page map context Error',
  88.      'Insufficient memory pages',
  89.      'Not enough free pages',
  90.      'Can''t allocate zero (0) pages',
  91.      'Logical page out of range',
  92.      'Physical page out of range',
  93.      'Page map hardware RAM full',
  94.      'Page map already has a Handle',
  95.      'Page map not mapped to Handle',
  96.      'Undefined subfunction number');
  97.  
  98. BEGIN
  99.   CASE Status OF
  100.     0        : WriteLn('Ok');
  101.     $80..$8F : WriteLn('EMM: ',EmmStatus[Status])
  102.     ELSE WriteLn('EMM: Unknown status = $',Hex(Status))
  103.     END
  104. END;
  105.  
  106.  
  107.  
  108. {******** Generic procedure to call the EMM interrupt **********}
  109.  
  110. PROCEDURE CallEmm(EmmFunction : Byte; VAR R : Registers);
  111.  
  112. BEGIN
  113.   R.AH := EmmFunction;
  114.   Intr(EmsInt,R);
  115.   IF (R.AH <> 0) THEN BEGIN
  116.     EmmPrintStatus(EmmRegs.AH);
  117.     Halt(EmmRegs.AH)
  118.     END
  119.   END;
  120.  
  121. {******************  Main Program  *****************************}
  122.  
  123.  
  124. BEGIN
  125.  
  126.   ClrScr;
  127.  
  128. {$DEFINE CheckFile}              {Undefine to test second method}
  129.  
  130. {$IFDEF CheckFile}                  {Check EMM driver - Method 1}
  131.  
  132.   GetIntVec(EmsInt,EmsVector);
  133.   PtrType(EmsVector).Offset := 10;
  134.   IF (DeviceName(EmsVector^) <> 'EMMXXXX0') THEN BEGIN
  135.     WriteLn('No EMM driver present');
  136.     Halt(1)
  137.     END;
  138.  
  139. {$ELSE}                             {Check EMM driver - Method 2}
  140.  
  141.   {***** Determine if EMM is installed by opening EMMXXXX0 *****}
  142.  
  143.   {$I-}
  144.   Assign(Tmp,'EMMXXXX0');
  145.   Reset(Tmp);
  146.   {$I+}
  147.   IF (IOResult <> 0) THEN BEGIN      {Opened file without error?}
  148.     WriteLn('No EMM driver present');
  149.     WriteLn('IO error #',IOResult:3);
  150.     Halt(1)
  151.     END;
  152.  
  153.   EmmRegs.AH := IOCtlFun              {Call IOCtl function to   }
  154.   EmmRegs.AL := $00;                  { test whether EMMXXXX0 is}
  155.   EmmRegs.BX := FileRec(Tmp).Handle;  { a file or a device      }
  156.  
  157.   MsDos(EmmRegs);
  158.   Close(Tmp);
  159.  
  160.   IF (EmmRegs.Flags AND 1) = 0 THEN            {Call successfull}
  161.     IF (EmmRegs.DX AND $80) = $80 THEN   {Handle is for a device}
  162.       WriteLn('Handle refers to a device')
  163.     ELSE BEGIN
  164.       WriteLn('Handle refers to a FILE');
  165.       WriteLn('Unable to contact EMM driver if present');
  166.       Halt(1)
  167.       END
  168.   ELSE BEGIN                                 {Call unsuccessfull}
  169.     CASE EmmRegs.AX OF
  170.       1 : WriteLn('Invalid IOCTL subfunction');
  171.       5 : WriteLn('Access to IOCTL denied');
  172.       6 : WriteLn('Invalid Handle')
  173.       ELSE WriteLn('Unknown error # ',Hex(EmmRegs.AX))
  174.       END;
  175.     WriteLn('Unable to contact EMM driver');
  176.     Halt(1)
  177.     END;
  178.  
  179.  
  180. {$ENDIF}
  181.  
  182.   WriteLn('EMM driver present');
  183.  
  184.   {********  Print the current status of the EMM driver ********}
  185.  
  186.   CallEmm(GetStatus,EmmRegs);
  187.   WriteLn('EMM Status Ok');
  188.  
  189.   {******** Print the version number of EMM driver *************}
  190.  
  191.   CallEmm(GetEmmVersion,EmmRegs);
  192.  
  193.   WriteLn('EMS driver version = ',
  194.            (EmmRegs.AL SHR 4):1,'.',
  195.            (EmmRegs.AL AND $0F):1);
  196.  
  197.   IF EmmRegs.AL < $32 THEN BEGIN
  198.     WriteLn('Error - EMM is version is earlier than 3.2');
  199.     Halt(1)
  200.     END;
  201.  
  202.   {***** Print the page frame & physical window addresses ******}
  203.  
  204.   CallEmm(GetPageFrameAddr,EmmRegs);
  205.  
  206.   PtrType(P0).Segment := EmmRegs.BX; { Window 0 -> P0 = BX:0000 }
  207.   PtrType(P0).Offset := $0;
  208.   PtrType(P1).Segment := EmmRegs.BX; { Window 1 -> P1 = BX:4000 }
  209.   PtrType(P1).Offset := $4000;
  210.   PtrType(P2).Segment := EmmRegs.BX; { Window 2 -> P2 = BX:8000 }
  211.   PtrType(P2).Offset := $8000;
  212.   PtrType(P3).Segment := EmmRegs.BX; { Window 3 -> P3 = BX:C000 }
  213.   PtrType(P3).Offset := $C000;
  214.  
  215.   WriteLn('Page frame segment address = ',Hex(EmmRegs.BX));
  216.   WriteLn('Physical page 0 address = ',PrintPointer(P0));
  217.   WriteLn('Physical page 1 address = ',PrintPointer(P1));
  218.   WriteLn('Physical page 2 address = ',PrintPointer(P2));
  219.   WriteLn('Physical page 3 address = ',PrintPointer(P3));
  220.  
  221.   {***** Print # of unallocated pages and total # of pages *****}
  222.  
  223.   CallEmm(GetUnallocPages,EmmRegs);
  224.   WriteLn('Total EMS pages = ',EmmRegs.DX:4);
  225.   WriteLn('Unused EMS pages = ',EmmRegs.BX:4);
  226.  
  227.   {***** Allocate some pages of expanded memory *****}
  228.  
  229.   EmmRegs.BX := (NumMsgs + MsgsPerPage) DIV MsgsPerPage;
  230.   CallEmm(AllocatePages,EmmRegs);
  231.   WriteLn('Allocated ',EmmRegs.BX,
  232.           ' pages to handle # ',EmmRegs.DX);
  233.   EmmHandle := EmmRegs.DX;
  234.  
  235.   {***** Load EMS RAM with data *****}
  236.  
  237.   MsgBuf := P0;               {* Set Message pointer to Page 0 *}
  238.  
  239.   FOR I := 0 TO NumMsgs-1 DO BEGIN
  240.     Str(I:4,StrNum);                       {Create msg string   }
  241.     Buff := ' EMS msg # ' + StrNum;
  242.     IF (I MOD 100) = 0 THEN Write('.');    {Dsp status on screen}
  243.     Page := I DIV MsgsPerPage;
  244.     Index := I MOD MsgsPerPage;
  245.     PtrType(MsgBuf).Offset := Index * SizeOf(Buff);
  246.  
  247.      {**** Map indicated logical page into physical page 0 ****}
  248.  
  249.     EmmRegs.AH := MapHandlePage;           {Map EMS page cmd    }
  250.     EmmRegs.BX := Page;                    {Logical page number }
  251.     EmmRegs.AL := 0;                       {Physical page 0     }
  252.     EmmRegs.DX := EmmHandle;               {EMM RAM handle      }
  253.  
  254.     Intr(EmsInt,EmmRegs);
  255.  
  256.     IF EmmRegs.AH = 0 THEN
  257.       Move(Buff[0],MsgBuf^,SizeOf(Buff))   {Set message into mem}
  258.     ELSE BEGIN
  259.       EmmPrintStatus(EmmRegs.AH);
  260.       I := NumMsgs
  261.       END
  262.     END;
  263.  
  264.     WriteLn;
  265.  
  266.   {******  Allow user to access any message in the buffer ******}
  267.  
  268.   I := $FF;
  269.   WHILE I <> -1 DO BEGIN
  270.     MsgBuf := P3;                 {Set MsgBuf to physical page 3}
  271.     Write('Enter message # to retrieve, or -1 to quit: ');
  272.     ReadLn(I);
  273.     IF (I >= 0) AND (I < NumMsgs) THEN BEGIN
  274.       Page := I DIV MsgsPerPage;
  275.       Index := I MOD MsgsPerPage;
  276.  
  277.         {**** Map indicated page into physical page 3 ****}
  278.  
  279.       EmmRegs.AH := MapHandlePage;         {Map EMM page command}
  280.       EmmRegs.BX := Page;                  {Logical page number }
  281.       EmmRegs.AL := 3;                     {Physical page 3     }
  282.       EmmRegs.DX := EmmHandle;             {EMM RAM handle      }
  283.  
  284.       Intr(EmsInt,EmmRegs);
  285.  
  286.       IF EmmRegs.AH = 0 THEN BEGIN
  287.         Inc(PtrType(MsgBuf).Offset,Index * SizeOf(Buff));
  288.         Move(MsgBuf^,Buff[0],SizeOf(Buff));
  289.         Write('Retrieved message -> ',Buff);
  290.         WriteLn(' from page #',Page:2,' Index',Index:5);
  291.         END
  292.       ELSE BEGIN
  293.         EmmPrintStatus(EmmRegs.AH);
  294.         I := -1;
  295.         END
  296.       END
  297.     END;
  298.  
  299.      {***** Free the EMS RAM back to the EMM driver ****}
  300.  
  301.   EmmRegs.DX := EmmHandle;
  302.   CallEmm(DeallocatePages,EmmRegs);
  303.   WriteLn('Released all memory for handle ',EmmRegs.DX:2);
  304. END.
  305.